<template>
  <el-dialog
    title="人脸验证"
    :visible="visible"
    width="500px"
    :before-close="handleClose"
    :close-on-click-modal="false"
    @close="onClose"
    class="face-taking"
  >
    <div
      class="face-taking-wrapper"
      v-loading="steps === 0"
      element-loading-text="正在打开摄像头"
      element-loading-spinner="el-icon-loading"
    >
      <div v-if="steps === 2" class="desc">没有开启摄像头权限或浏览器版本不兼容</div>
      <template v-else>
        <video
          v-show="!imgSrc"
          id="videoCamera"
          class="canvas"
          :width="videoWidth"
          :height="videoHeight"
          autoPlay
        ></video>
        <canvas
          v-show="imgSrc"
          id="canvasCamera"
          class="canvas"
          :width="videoWidth"
          :height="videoHeight"
        ></canvas>
      </template>
    </div>
    <div slot="footer" v-if="steps === 1">
      <!-- 验证 -->
      <el-button @click="drawImage" size="small" type="primary" :loading="loading">
        {{ loading ? '验证中…' : '拍照' }}
      </el-button>
    </div>
  </el-dialog>
</template>

<script>
export default {
  props: {
    visible: Boolean,
    id: Number
  },
  data() {
    return {
      url: '', // 上传的图片的地址
      videoWidth: 500, // 绘画布的宽高
      videoHeight: 500,
      thisCancas: null,
      thisContext: null,
      thisVideo: null,
      imgSrc: '',
      imgFile: null,
      steps: 0,
      loading: false
    }
  },
  mounted() {
    this.onTake()
  },
  methods: {
    /*调用摄像头拍照开始*/
    onTake() {
      this.getCompetence()
    },

    /*关闭弹窗，以及关闭摄像头功能*/
    onClose() {
      this.$emit('update:visible', false)
      this.stopNavigator() // 关闭摄像头
    },

    // 调用摄像头权限
    getCompetence() {
      //必须在model中render后才可获取到dom节点,直接获取无法获取到model中的dom节点
      this.$nextTick(() => {
        const _this = this
        // 获取画布节点
        this.thisCancas = document.getElementById('canvasCamera')
        // 为画布指定绘画为2d类型
        this.thisContext = this.thisCancas.getContext('2d')
        //获取video节点
        this.thisVideo = document.getElementById('videoCamera')
        // 旧版本浏览器可能根本不支持mediaDevices，我们首先设置一个空对象
        if (navigator.mediaDevices === undefined) {
          navigator.menavigatordiaDevices = {}
        }
        // 一些浏览器实现了部分mediaDevices，我们不能只分配一个对象
        // 使用getUserMedia，因为它会覆盖现有的属性。
        // 这里，如果缺少getUserMedia属性，就添加它。
        if (navigator.mediaDevices.getUserMedia === undefined) {
          navigator.mediaDevices.getUserMedia = function(constraints) {
            // 首先获取现存的getUserMedia(如果存在)
            let getUserMedia =
              navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.getUserMedia
            // 有些浏览器不支持，会返回错误信息
            // 保持接口一致
            if (!getUserMedia) {
              return Promise.reject(new Error('getUserMedia is not implemented in this browser'))
            }
            // 否则，使用Promise将调用包装到旧的navigator.getUserMedia
            return new Promise(function(resolve, reject) {
              getUserMedia.call(navigator, constraints, resolve, reject)
            })
          }
        }
        const constraints = {
          audio: false,
          video: {
            width: _this.videoWidth,
            height: _this.videoHeight,
            transform: 'scaleX(-1)'
          }
        }
        navigator.mediaDevices
          .getUserMedia(constraints)
          .then(function(stream) {
            // 旧的浏览器可能没有srcObject
            if ('srcObject' in _this.thisVideo) {
              _this.thisVideo.srcObject = stream
            } else {
              // 避免在新的浏览器中使用它，因为它正在被弃用。
              _this.thisVideo.src = window.URL.createObjectURL(stream)
            }
            _this.thisVideo.onloadedmetadata = function(e) {
              _this.thisVideo.play()
            }
            _this.steps = 1
          })
          .catch(() => {
            _this.steps = 2
          })
      })
    },

    //调用摄像头 --- 进行绘制图片
    drawImage() {
      // 点击，canvas画图
      this.thisContext.drawImage(this.thisVideo, 0, 0, this.videoWidth, this.videoHeight)
      // 获取图片base64链接
      this.imgSrc = this.thisCancas.toDataURL('image/png')
      this.onCancel()
    },
    //清空画布
    clearCanvas(id) {
      let c = document.getElementById(id)
      let cxt = c.getContext('2d')
      cxt.clearRect(0, 0, c.width, c.height)
    },

    //重置画布
    resetCanvas() {
      this.imgSrc = ''
      this.clearCanvas('canvasCamera')
    },

    //关闭摄像头
    stopNavigator() {
      if (this.steps === 1) {
        this.thisVideo.srcObject.getTracks()[0].stop()
      }
    },
    /*调用摄像头拍照结束*/

    /*完成拍照并对其照片进行上传*/
    onCancel() {
      this.loading = true
      this.imgFile = this.dataURLtoFile(this.imgSrc, new Date() + '.png')
      let data = new FormData()
      data.append('file', this.imgFile)
      data.append('scene_key', 'course')
      data.append('scene_id', this.id)
      setTimeout(() => {
        this.loading = false
        this.onClose()
        this.$emit('cancel')
      }, 1000)
      // 验证人脸
      /* this.$api.postTencentFacePersonVerify(
        data,
        (res) => {
          this.$message.success(res.msg)
          this.loading = false
          this.onClose()
          this.$emit('cancel')
        },
        (error) => {
          this.resetCanvas()
          this.$message.error(error.msg)
          this.loading = false
        }
      ) */
    },

    dataURLtoFile(dataurl, filename) {
      var arr = dataurl.split(',')
      var mime = arr[0].match(/:(.*?);/)[1]
      var bstr = atob(arr[1])
      var n = bstr.length
      var u8arr = new Uint8Array(n)
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }
      return new File([u8arr], filename, { type: mime })
    }
  },
  beforeDestroy() {
    this.onClose()
  }
}
</script>

<style lang="scss" scoped>
.face-taking {
  ::v-deep .el-dialog__header {
    border-bottom: 1px solid #e4e7ed;
  }
  ::v-deep .el-dialog__body {
    padding: 0;
  }
  ::v-deep .el-dialog__footer {
    text-align: center;
  }
  .face-taking-wrapper {
    width: 500px;
    height: 500px;
    display: flex;
    align-items: center;
    justify-content: center;
    .desc {
      font-size: 13px;
      font-weight: 400;
      color: $text-color-auxiliary;
    }
  }
}
</style>
